#include "BikeCommandUtil.h"
#include "CommandConstants.h"  // 你可以包含其他头文件来引入所需的常量
#include "CalMetricDataUtil.h"  // 处理相关的计算

#include <iostream>
#include <iomanip>
#include <sstream>

unsigned char BikeCommandUtil::sender = 0;
unsigned char BikeCommandUtil::length = 0;
std::vector<unsigned char> BikeCommandUtil::operationCode;
std::vector<unsigned char> BikeCommandUtil::data;
unsigned char BikeCommandUtil::checksum = 0;
unsigned char BikeCommandUtil::end = 0;
std::string BikeCommandUtil::operatorCommand = "";
double BikeCommandUtil::units[15] = {0.01, 0.01, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 0.1, 1, 1};
int BikeCommandUtil::bitsForEvery[15] = {2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2};

std::string BikeCommandUtil::parseCommand(const std::string& command) {
    // 将十六进制字符串转换为字节数组
    std::vector<unsigned char> bytes = hexStringToByteArray(command);

    // 提取各个部分
    sender = bytes[0];
    length = bytes[1];
    operationCode.assign(bytes.begin() + 2, bytes.begin() + 4);
    data.assign(bytes.begin() + 4, bytes.end() - 2); // 除去校验和和结束符
    checksum = bytes[bytes.size() - 2];
    end = bytes[bytes.size() - 1];
    operatorCommand = command.substr(4, 4);

    // 打印解析命令后的各种信息
    // print();

    // 验证Length是否错误
    if ((length & 0xFF) != operationCode.size() + data.size() + 1) {
        std::cout << "Length字段不符合要求" << std::endl;
        return "The length is not correct";
    }

    // 验证校验码是否错误
    if (calculateChecksum(operationCode, data) != (checksum & 0xFF)) {
        std::cout << "计算所得的校验码为：0x" << std::hex << calculateChecksum(operationCode, data) << std::endl;
        std::cout << "校验码不一致" << std::endl;
        return "The checksum is not correct";
    }

    std::cout << "parse success!" << std::endl;

    // 根据具体的命令处理
    std::string res = processOperatorCommand(operatorCommand);

    // std::cout << "After parsing: " << res << std::endl;

    return res;
}

int BikeCommandUtil::calculateChecksum(const std::vector<unsigned char>& operationCode, const std::vector<unsigned char>& data) {
    int sum = 0;
    for (unsigned char b : operationCode) {
        sum += (b & 0xFF); // 确保将字节转换为无符号整数
    }
    for (unsigned char b : data) {
        sum += (b & 0xFF); // 确保将字节转换为无符号整数
    }
    return sum & 0xFF; // 取低位字节作为校验和
}

std::string BikeCommandUtil::processOperatorCommand(const std::string& operatorCommand) {
    if (operatorCommand == CommandConstants::IndoorBikeData) {
        std::cout << "Starting Cal Bike Params" << std::endl;
        std::vector<int> ans = parseFitnessData(data);
        return CalMetricDataUtil::cal(ans);
    } else if (operatorCommand == CommandConstants::FitnessMachineControlPoint) {
        std::cout << "This is Fitness Machine Control Point" << std::endl;
        return "Fitness Machine Control Point";
    } else if (operatorCommand == CommandConstants::ManufacturerNameString) {
        std::string deviceName = byteArrayToString(data);
        std::cout << "Device Name: " << deviceName << std::endl;
        return deviceName;
    } else if (operatorCommand == CommandConstants::DeviceName) {
        std::string manufacturerName = byteArrayToString(data);
        std::cout << "Manufacturer Name: " << manufacturerName << std::endl;
        return manufacturerName;
    } else if (operatorCommand == CommandConstants::HardwareRevisionString) {
        std::string hardwareName = byteArrayToString(data);
        std::cout << "Hardware Name: " << hardwareName << std::endl;
        return hardwareName;
    } else if (operatorCommand == CommandConstants::FirmwareRevisionString) {
        std::string firmwareName = byteArrayToString(data);
        std::cout << "Firmware Name: " << firmwareName << std::endl;
        return firmwareName;
    } else {
        std::cout << "Unknown Command" << std::endl;
        return "Unknown Command";
    }
}

std::vector<unsigned char> BikeCommandUtil::hexStringToByteArray(const std::string& s) {
    std::vector<unsigned char> data(s.length() / 2);
    for (size_t i = 0; i < s.length(); i += 2) {
        data[i / 2] = (unsigned char)((std::stoi(s.substr(i, 1), nullptr, 16) << 4)
                                      + std::stoi(s.substr(i + 1, 1), nullptr, 16));
    }
    return data;
}

std::string BikeCommandUtil::bytesToHex(const std::vector<unsigned char>& bytes, int len) {
    std::stringstream ss;
    for (int i = 0; i < len; ++i) {
        ss << std::hex << std::setw(2) << std::setfill('0') << (int)bytes[i];
    }
    return ss.str();
}

std::string BikeCommandUtil::byteArrayToString(const std::vector<unsigned char>& byteArray) {
    std::string result(byteArray.begin(), byteArray.end());
    return result;
}

void BikeCommandUtil::print() {
    std::cout << "Sender: 0x" << std::hex << (int)sender << std::endl;
    std::cout << "Length: 0x" << std::hex << (int)length << std::endl;
    std::cout << "Operation Code: " << bytesToHex(operationCode, operationCode.size()) << std::endl;
    std::cout << "Data: " << bytesToHex(data, data.size()) << std::endl;
    std::cout << "Checksum: 0x" << std::hex << (int)checksum << std::endl;
    std::cout << "End: 0x" << std::hex << (int)end << std::endl;
}

std::vector<int> BikeCommandUtil::parseFitnessData(const std::vector<unsigned char>& bytes) {
    std::vector<int> ans;
    if (bytes.size() < 10) {
        std::cout << "数据长度不足" << std::endl;
        return ans;
    }

    int speed = (bytes[3] << 8) | (bytes[2] & 0xFF); // 合并高低字节
    ans.push_back(speed);

    int cadence = (bytes[5] << 8) | (bytes[4] & 0xFF); // 合并高低字节
    ans.push_back(cadence);

    int resistanceLevel = (bytes[7] << 8) | (bytes[6] & 0xFF);
    ans.push_back(resistanceLevel);

    int power = (bytes[9] << 8) | (bytes[8] & 0xFF);
    ans.push_back(power);

    return ans;
}

std::vector<int> BikeCommandUtil::parse(const std::vector<unsigned char>& bytes) {
    std::vector<int> results;
    int offset = 0;
    for (int i = 0; i < 15; ++i) {
        int len = bitsForEvery[i];
        double scale = units[i];
        int result = parseData(bytes, offset, len, scale);
        results.push_back(result);
        offset += len;
    }
    return results;
}

int BikeCommandUtil::parseData(const std::vector<unsigned char>& bytes, int offset, int len, double scale) {
    int value = 0;
    for (int i = 0; i < len; ++i) {
        value |= (bytes[offset + i] & 0xFF) << (8 * i);
    }
    return static_cast<int>(value * scale);
}
